---
title: Problem Solving
description: >
  Notes on a basic problem solving approach and how it
  relates to algorithms and computer science.
categories: posts
tags: [algorithms]
---

<details markdown="1" id="table-of-contents">
<summary>
Table of Contents
</summary>

* TOC
{:toc}
</details>

## Basic Problem-Solving Approach

Computer science is, ultimately, about problem solving. The way we reason and
solve a problem is known as an algorithm.
Studying how algorithms work as well as their efficiency is important and beyond
the scope of this post.
Here we'll only cover a basic problem-solving approach, outline application
development, and mention a few things to consider while developing an algorithm.

### 1. Plan

Start by planning how to find a solution to the problem at hand. List all known
facts as well as those we wish we knew. We should change our plan as we learn
more about the problem domain.

### 2. Understand the problem

When we understand a problem we are able to answer most questions about it.
In order to understand a problem we need to get rid of ambiguities, and wrong
assumptions. Asking for clarification should get rid of the former. While
restating the problem should get rid of wrong assumptions.
Whenever we need extra help understanding a problems we could:

#### Deconstruct the problem

Break the problem into steps or phases that are easier to solve.

#### Reuse knowledge

Learn to recognize different problems with similar solutions.

#### Reduce the scope of the problem

Deduction should help in developing an answer. We could make a table of values.
Extend it if possible. Use that data for automated tests.

### 3. Experiment

Try things, observe the results. No guessing, though.

### 4. Don't get frustrated

Solving problems can get overwhelming quickly specially when our understanding
of the problem is less than ideal; which is the norm. When that happens, go over
the techniques for understanding a problem.

## Application Development

A simplistic way of describing application development would be:

- Understand the problem.
- Create an algorithm. Outline a solution in plain language.
- Implement the algorithm. Translate the solution into code.
- Test the code as you write it to prevent bugs.
- Improve the system based on its own needs. Re-implement algorithms.

Each of these points cover several books. Learning all about them is part of
how we solve problems with code.

As we can see, the first two points of the previous section are closely related
with how we understand a problem and the algorithm we create to solve it. The
experimentation gets done while we implement and test the algorithm.

Check notes under Racket for a systematic approach at application development.

## Algorithm Design

Finally, here's a few things to consider when designing an algorithm:

- Randomization. Useful when the problem includes worst cases that could be
avoided by making part of the process random.
- Probability. This involves making educated guesses to find a solution.
- Adaptive techniques. Make use of approaches that focus on specific parts of
the problem first.
- Data structures. Find the inherent structure of the data and check if a data
structure has similar behavior to the one needed to solve the problem.
- Problem structure. Check if the problem's structure is naturally recursive,
hierarchical, or similar to a network. Also, check if we can use tree or network
algorithms to search the data.
- Decision trees. Consider applying a decision tree search method to the problem.
But keep in mind that perhaps a divide-and-conquer approach would be better.
